<?php

Raise::load('core.RaiseValidator');

/**
 * RaiseCompareValidator
 *
 * @author Sam-Mauris Yong / hellclanner at live dot com
 * @license http://www.opensource.org/licenses/bsd-license New BSD License
 * @package phpraise.core.validator
 * @since 1.2
 */
class RaiseCompareValidator extends RaiseValidator {

    /**
     * Equals
     */
    const OPERATOR_EQUALS = 1;

    /**
     * More than
     */
    const OPERATOR_MORE_THAN = 2;

    /**
     * Less than
     */
    const OPERATOR_LESS_THAN = 4;

    /**
     * Not equals
     */
    const OPERATOR_NOT_EQUALS = 8;

    /**
     * Compare the data type instead of value
     */
    const OPERATOR_DATA_TYPE = 16;

    /**
     * Comparison is strict for value and data type comparison
     * Note that for data type comparison, if this flag is entered, it will compare
     */
    const OPERATOR_STRICT = 32;

    private $operator;

    /**
     * Base to compare against the value.
     * @var mixed
     */
    private $base;

    /**
     * Get or set the operator to compare the base and value.
     * Valid comparisons include:<br /><ul>
     *     <li>OPERATOR_MORE_THAN | OPERATOR_EQUALS</li>
     *     <li>OPERATOR_LESS_THAN | OPERATOR_EQUALS</li>
     *     <li>OPERATOR_MORE_THAN</li>
     *     <li>OPERATOR_LESS_THAN</li>
     *     <li>OPERATOR_STRICT | OPERATOR_EQUALS</li>
     *     <li>OPERATOR_STRICT | OPERATOR_NOT_EQUALS</li>
     *     <li>OPERATOR_EQUALS</li>
     *     <li>OPERATOR_NOT_EQUALS</li>
     *     <li>OPERATOR_DATA_TYPE | OPERATOR_EQUALS</li>
     *     <li>OPERATOR_DATA_TYPE | OPERATOR_NOT_EQUALS</li>
     *     <li>OPERATOR_DATA_TYPE | OPERATOR_EQUALS | OPERATOR_STRICT</li>
     *     <li>OPERATOR_DATA_TYPE | OPERATOR_NOT_EQUALS | OPERATOR_STRICT</li>
     * </ul>
     * @param int $o
     * @return int
     */
    public function operator($o = null){
        if(func_num_args() == 1){
            $this->operator = $o;
        }
        return $this->operator;
    }

    /**
     * Get or set the base to compare against the value.
     * @param mixed $b
     * @return mixed
     */
    public function base($b = null){
        if(func_num_args() == 1){
            $this->base = $b;
        }
        return $this->base;
    }

    /**
     * Validate the value against the base by comparing
     * @param mixed $value
     */
    public function validate($value) {
        if($this->operator() & self::OPERATOR_DATA_TYPE){
            // comparing data type
            if($this->operator() & self::OPERATOR_STRICT){
                if(is_object($value)){
                    if(($this->operator() & self::OPERATOR_EQUALS) && get_class($value) == $this->base()){
                        return true;
                    }
                    if(($this->operator() & self::OPERATOR_NOT_EQUALS) && get_class($value) != $this->base()){
                        return true;
                    }
                    return false;
                }
            }
            if(($this->operator() & self::OPERATOR_EQUALS) && gettype($value) == $this->base()){
                return true;
            }
            if(($this->operator() & self::OPERATOR_NOT_EQUALS) && gettype($value) != $this->base()){
                return true;
            }
        }else{
            if($this->operator() & self::OPERATOR_STRICT){
                if(($this->operator() & self::OPERATOR_EQUALS) && $value === $this->base()){
                    return true;
                }
                if(($this->operator() & self::OPERATOR_NOT_EQUALS) && $value !== $this->base()){
                    return true;
                }
            }else{
                if(($this->operator() & (self::OPERATOR_MORE_THAN | self::OPERATOR_EQUALS)) && $value >= $this->base()){
                    return true;
                }
                if(($this->operator() & (self::OPERATOR_LESS_THAN | self::OPERATOR_EQUALS)) && $value <= $this->base()){
                    return true;
                }
                if(($this->operator() & self::OPERATOR_LESS_THAN) && $value < $this->base()){
                    return true;
                }
                if(($this->operator() & self::OPERATOR_MORE_THAN) && $value > $this->base()){
                    return true;
                }
                if(($this->operator() & self::OPERATOR_NOT_EQUALS) && $value != $this->base()){
                    return true;
                }
                if(($this->operator() & self::OPERATOR_EQUALS) && $value == $this->base()){
                    return true;
                }
            }

        }
        return false;
    }

}

